/**
 * 超深度上下文Prompt增强器（Fuzz Test）
 * 
 * 基于ultra-deep-context学习数据，为Fuzz生成提供：
 * 1. 真实项目的Fuzzer实现示例
 * 2. 数据构造和NDK接口调用模式
 * 3. 头文件推荐和依赖分析
 * 4. Fuzzer框架正确使用方法
 */

import * as fs from 'fs';
import * as path from 'path';

interface FuzzContext {
    fuzzFile: string;
    fuzzerFunction: string;
    functionBody: string;
    includes: string[];
    ndkInterfaces: string[];
    calledFunctions: string[];
    dataConstructionPatterns: string[];
    fuzzerFrameworkUsage: string[];
    buildGn?: string;
}

interface UltraDeepIndex {
    stats: any;
    sourceToTestMapping: Record<string, string[]>;
    sourceToFuzzMapping: Record<string, string[]>;
    gnRelationships: any[];
    testBatches: number;
    fuzzBatches: number;
    mockBatches: number;
}

export class UltraDeepFuzzPromptEnhancer {
    private static knowledgeDir = path.join(__dirname, '../../../../core/knowledge');
    private static index: UltraDeepIndex | null = null;
    private static fuzzContextsCache: FuzzContext[] = [];
    
    /**
     * 初始化：加载索引文件
     */
    private static loadIndex(): UltraDeepIndex {
        if (this.index) {
            return this.index;
        }
        
        const indexPath = path.join(this.knowledgeDir, 'ultra-deep-index.json');
        if (fs.existsSync(indexPath)) {
            this.index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
            return this.index as UltraDeepIndex;
        }
        
        console.warn('[UltraDeepFuzzPromptEnhancer] 索引文件不存在，将使用基础Prompt');
        return {
            stats: {},
            sourceToTestMapping: {},
            sourceToFuzzMapping: {},
            gnRelationships: [],
            testBatches: 0,
            fuzzBatches: 0,
            mockBatches: 0
        };
    }
    
    /**
     * 加载Fuzz上下文（懒加载，只加载需要的批次）
     */
    private static loadFuzzContexts(maxSamples: number = 100): FuzzContext[] {
        if (this.fuzzContextsCache.length > 0) {
            return this.fuzzContextsCache.slice(0, maxSamples);
        }
        
        const index: UltraDeepIndex = this.loadIndex();
        const contexts: FuzzContext[] = [];
        
        // 加载前2个批次（1000个Fuzz文件）
        const batchesToLoad = Math.min(2, index.fuzzBatches);
        for (let i = 0; i < batchesToLoad; i++) {
            const batchPath = path.join(this.knowledgeDir, `ultra-deep-fuzz-${i}.json`);
            if (fs.existsSync(batchPath)) {
                const batch = JSON.parse(fs.readFileSync(batchPath, 'utf-8'));
                contexts.push(...batch);
            }
        }
        
        this.fuzzContextsCache = contexts;
        return contexts.slice(0, maxSamples);
    }
    
    /**
     * 核心方法：增强Fuzz生成Prompt
     */
    public static enhancePrompt(
        basePrompt: string,
        sourceCode: string,
        functionName?: string
    ): string {
        console.log(`\n🔮 [UltraDeepFuzzPromptEnhancer] 开始增强Prompt...`);
        
        const index: UltraDeepIndex = this.loadIndex();
        if (!index || !this.index || index.fuzzBatches === 0) {
            console.warn('[UltraDeepFuzzPromptEnhancer] 未找到学习数据，使用基础Prompt');
            return basePrompt;
        }
        
        // 1. 分析源码特征
        const features = this.analyzeSourceFeatures(sourceCode, functionName);
        console.log(`   特征分析: 包含${features.includes.length}个头文件, ${features.ndkInterfaces.length}个NDK接口`);
        
        // 2. 查找相似的Fuzzer示例
        const similarFuzzers = this.findSimilarFuzzers(features, 5);
        console.log(`   找到${similarFuzzers.length}个相似Fuzzer示例`);
        
        // 3. 提取NDK接口模式
        const ndkPatterns = this.extractNDKPatterns(features);
        console.log(`   提取了${ndkPatterns.length}个NDK调用模式`);
        
        // 4. 构建增强Prompt
        let enhancedPrompt = basePrompt;
        
        // 添加真实项目的Fuzzer示例
        if (similarFuzzers.length > 0) {
            enhancedPrompt += '\n\n## 📚 真实项目的Fuzzer实现示例（供参考学习）\n\n';
            enhancedPrompt += '以下是OpenHarmony项目中的真实Fuzzer代码，请参考其风格和模式：\n\n';
            
            similarFuzzers.forEach((fuzz, idx) => {
                enhancedPrompt += `### 示例${idx + 1}：${path.basename(fuzz.fuzzFile, '.cpp')}\n\n`;
                enhancedPrompt += '```cpp\n';
                // 截取前100行避免Prompt过长
                const lines = fuzz.functionBody.split('\n').slice(0, 100);
                enhancedPrompt += lines.join('\n');
                if (fuzz.functionBody.split('\n').length > 100) {
                    enhancedPrompt += '\n    // ... 更多Fuzzer逻辑 ...\n';
                }
                enhancedPrompt += '\n```\n\n';
                
                // 关键信息提取
                if (fuzz.ndkInterfaces.length > 0) {
                    enhancedPrompt += `**NDK接口调用**: ${fuzz.ndkInterfaces.slice(0, 5).join(', ')}\n\n`;
                }
                if (fuzz.dataConstructionPatterns.length > 0) {
                    enhancedPrompt += `**数据构造模式**: ${fuzz.dataConstructionPatterns.slice(0, 3).join(', ')}\n\n`;
                }
                if (fuzz.fuzzerFrameworkUsage.length > 0) {
                    enhancedPrompt += `**框架使用**: ${fuzz.fuzzerFrameworkUsage.slice(0, 3).join(', ')}\n\n`;
                }
            });
        }
        
        // 添加NDK接口调用模式
        if (ndkPatterns.length > 0) {
            enhancedPrompt += '\n\n## 🎯 NDK接口调用模式（必须遵循）\n\n';
            enhancedPrompt += '以下是OpenHarmony NDK接口的常见调用模式，请严格遵循：\n\n';
            
            ndkPatterns.forEach((pattern, idx) => {
                enhancedPrompt += `${idx + 1}. ${pattern}\n`;
            });
            enhancedPrompt += '\n';
        }
        
        // 添加数据构造指导
        enhancedPrompt += '\n\n## 🔨 Fuzz数据构造最佳实践\n\n';
        enhancedPrompt += '基于OpenHarmony项目的Fuzzer实践，数据构造应遵循：\n\n';
        enhancedPrompt += '1. **数据大小校验**: 始终检查`size >= sizeof(类型)`，确保数据足够\n';
        enhancedPrompt += '2. **指针安全**: 使用`reinterpret_cast`前验证数据有效性\n';
        enhancedPrompt += '3. **字符串处理**: 对于字符串参数，使用`std::string(reinterpret_cast<const char*>(data), size)`\n';
        enhancedPrompt += '4. **结构体解析**: 从data中提取多个字段时，使用偏移量：`data + offset`\n';
        enhancedPrompt += '5. **边界测试**: 构造空数据、超大数据、特殊字符等边界情况\n\n';
        
        // 添加头文件推荐
        const recommendedHeaders = this.recommendHeaders(features);
        if (recommendedHeaders.length > 0) {
            enhancedPrompt += '\n\n## 📦 推荐的头文件（基于类似Fuzzer）\n\n';
            enhancedPrompt += '```cpp\n';
            recommendedHeaders.forEach(header => {
                enhancedPrompt += `#include ${header}\n`;
            });
            enhancedPrompt += '```\n\n';
        }
        
        // 添加关键提示
        enhancedPrompt += '\n\n## ⚠️ Fuzzer代码关键要求（必须严格遵守）\n\n';
        enhancedPrompt += '1. **函数签名**: 必须使用标准签名 `extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)`\n';
        enhancedPrompt += '2. **头文件完整**: 包含所有必要的头文件，特别是NDK接口的头文件（如`<native_xxx.h>`）\n';
        enhancedPrompt += '3. **数据安全**: 所有从data读取的操作必须有边界检查\n';
        enhancedPrompt += '4. **返回值**: 始终返回0表示成功\n';
        enhancedPrompt += '5. **OH_前缀**: 对于NDK接口，确保函数名以`OH_`开头（如`OH_NativeWindow_CreateNativeWindow`）\n';
        enhancedPrompt += '6. **资源释放**: 调用创建类接口后，必须调用对应的释放接口（如`OH_xxx_Destroy`）\n';
        enhancedPrompt += '7. **无输出**: Fuzzer中不应包含`printf`、`std::cout`等输出语句\n\n';
        
        console.log(`✅ [UltraDeepFuzzPromptEnhancer] Prompt增强完成！`);
        console.log(`   原始长度: ${basePrompt.length} 字符`);
        console.log(`   增强后长度: ${enhancedPrompt.length} 字符 (+${enhancedPrompt.length - basePrompt.length})\n`);
        
        return enhancedPrompt;
    }
    
    /**
     * 分析源码特征
     */
    private static analyzeSourceFeatures(sourceCode: string, functionName?: string): any {
        const features = {
            includes: [] as string[],
            ndkInterfaces: [] as string[],
            classes: [] as string[],
            keywords: [] as string[],
            functionName: functionName
        };
        
        // 提取include
        const includeRegex = /#include\s+[<"]([^>"]+)[>"]/g;
        let match;
        while ((match = includeRegex.exec(sourceCode)) !== null) {
            features.includes.push(match[1]);
        }
        
        // 提取NDK接口（OH_开头的函数调用）
        const ndkRegex = /\b(OH_[A-Za-z0-9_]+)\s*\(/g;
        while ((match = ndkRegex.exec(sourceCode)) !== null) {
            features.ndkInterfaces.push(match[1]);
        }
        
        // 提取类名
        const classRegex = /\b([A-Z][a-zA-Z0-9_]*)::[a-zA-Z0-9_]+\(/g;
        while ((match = classRegex.exec(sourceCode)) !== null) {
            features.classes.push(match[1]);
        }
        
        // 提取关键字
        if (sourceCode.includes('NativeWindow')) features.keywords.push('NativeWindow');
        if (sourceCode.includes('NativeBuffer')) features.keywords.push('NativeBuffer');
        if (sourceCode.includes('reinterpret_cast')) features.keywords.push('reinterpret_cast');
        if (sourceCode.includes('sizeof')) features.keywords.push('sizeof');
        
        return features;
    }
    
    /**
     * 查找相似的Fuzzer示例
     */
    private static findSimilarFuzzers(features: any, limit: number = 5): FuzzContext[] {
        const fuzzers = this.loadFuzzContexts(200);
        
        // 计算相似度并排序
        const scored = fuzzers.map(fuzz => {
            let score = 0;
            
            // 头文件匹配
            const commonIncludes = fuzz.includes.filter(inc => 
                features.includes.some((f: string) => f.includes(inc) || inc.includes(f))
            );
            score += commonIncludes.length * 3;
            
            // NDK接口匹配（高权重）
            const commonNDK = fuzz.ndkInterfaces.filter(ndk => 
                features.ndkInterfaces.includes(ndk)
            );
            score += commonNDK.length * 10;
            
            // 类名匹配
            const commonClasses = features.classes.filter((cls: string) => 
                fuzz.functionBody.includes(cls)
            );
            score += commonClasses.length * 5;
            
            // 关键字匹配
            const commonKeywords = features.keywords.filter((kw: string) => 
                fuzz.functionBody.includes(kw)
            );
            score += commonKeywords.length * 2;
            
            // 数据构造模式丰富度
            score += fuzz.dataConstructionPatterns.length * 2;
            
            // Fuzzer函数长度（偏好中等长度，30-150行）
            const bodyLines = fuzz.functionBody.split('\n').length;
            if (bodyLines >= 30 && bodyLines <= 150) {
                score += 5;
            }
            
            return { fuzz, score };
        });
        
        // 按分数排序并返回
        return scored
            .filter(item => item.score > 0)
            .sort((a, b) => b.score - a.score)
            .slice(0, limit)
            .map(item => item.fuzz);
    }
    
    /**
     * 提取NDK调用模式
     */
    private static extractNDKPatterns(features: any): string[] {
        const fuzzers = this.loadFuzzContexts(100);
        const patterns: string[] = [];
        const patternSet = new Set<string>();
        
        // 收集所有包含NDK接口的Fuzzer的调用模式
        fuzzers.forEach(fuzz => {
            if (fuzz.ndkInterfaces.length > 0) {
                fuzz.ndkInterfaces.forEach(ndk => {
                    // 提取调用模式（简化版）
                    const pattern = `${ndk}(...) 的典型用法`;
                    if (!patternSet.has(pattern)) {
                        patternSet.add(pattern);
                        patterns.push(pattern);
                    }
                });
            }
        });
        
        return patterns.slice(0, 10); // 最多返回10个模式
    }
    
    /**
     * 推荐头文件
     */
    private static recommendHeaders(features: any): string[] {
        const fuzzers = this.loadFuzzContexts(100);
        const headerFrequency = new Map<string, number>();
        
        // 统计相似Fuzzer中的头文件频率
        fuzzers.forEach(fuzz => {
            fuzz.includes.forEach(inc => {
                headerFrequency.set(inc, (headerFrequency.get(inc) || 0) + 1);
            });
        });
        
        // 推荐高频头文件
        const recommended = Array.from(headerFrequency.entries())
            .filter(([header]) => {
                // 过滤掉已存在的头文件
                return !features.includes.some((f: string) => f === header);
            })
            .sort((a, b) => b[1] - a[1])
            .slice(0, 10)
            .map(([header]) => {
                // 格式化为include语句
                if (header.startsWith('<') || header.startsWith('"')) {
                    return header;
                }
                return `<${header}>`;
            });
        
        return recommended;
    }
}

